package com.lytfly.flowable.modules.flow.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.lytfly.flowable.domain.ProcessStatusEnum;
import com.lytfly.flowable.modules.flow.entity.FlowExtendHisprocinst;
import com.lytfly.flowable.modules.flow.entity.FlowExtendProcinst;
import com.lytfly.flowable.modules.flow.mapper.FlowExtendHisprocinstMapper;
import com.lytfly.flowable.modules.flow.service.IFlowExtendHisprocinstService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lytfly.flowable.modules.flow.service.IFlowExtendProcinstService;
import org.flowable.engine.HistoryService;
import org.flowable.engine.history.HistoricProcessInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

/**
 * <p>
 * 历史实例的扩展 服务实现类
 * </p>
 *
 * @author liuyuantao
 * @since 2021年07月15日 12时07分
 */
@Service
public class FlowExtendHisprocinstServiceImpl extends ServiceImpl<FlowExtendHisprocinstMapper, FlowExtendHisprocinst> implements IFlowExtendHisprocinstService {

    @Lazy
    @Autowired
    private IFlowExtendProcinstService extendProcinstService;
    @Autowired
    private HistoryService historyService;

    /**
     * 通过流程实例获取历史时的扩展信息
     *
     * @param processInstanceId 流程实例id
     * @return
     */
    @Override
    public FlowExtendHisprocinst findExtendHisprocinstByProcessInstanceId(String processInstanceId) {
        LambdaQueryWrapper<FlowExtendHisprocinst> extendHisprocinstLambdaQueryWrapper = new LambdaQueryWrapper<>();
        extendHisprocinstLambdaQueryWrapper.eq(FlowExtendHisprocinst::getProcessInstanceId, processInstanceId);
        return this.getOne(extendHisprocinstLambdaQueryWrapper);
    }

    /**
     * 更新流程实例的状态
     *
     * @param extendHisprocinst 历史流程实例扩展信息
     */
    @Override
    public void updateAllStatusByProcessInstanceId(FlowExtendHisprocinst extendHisprocinst) {
        FlowExtendHisprocinst hisprocinst = findExtendHisprocinstByProcessInstanceId(extendHisprocinst.getProcessInstanceId());
        this.updateStatusByProcessInstanceId(hisprocinst.getProcessStatus(), extendHisprocinst.getProcessStatus(), extendHisprocinst.getProcessInstanceId());
        //处理子流程的扩展信息
        HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(extendHisprocinst.getProcessInstanceId()).singleResult();
        if (historicProcessInstance != null) {
            String rootProcessInstanceId = historicProcessInstance.getSuperProcessInstanceId();
            if (StrUtil.isNotBlank(rootProcessInstanceId) && !rootProcessInstanceId.equals(extendHisprocinst.getProcessInstanceId())) {
                hisprocinst = this.findExtendHisprocinstByProcessInstanceId(rootProcessInstanceId);
                this.updateStatusByProcessInstanceId(hisprocinst.getProcessStatus(), extendHisprocinst.getProcessStatus(), rootProcessInstanceId);
            }
        }
    }

    /**
     * 更新扩展的历史流程状态
     *
     * @param oldStatus
     * @param status
     * @param processInstanceId
     */
    private void updateStatusByProcessInstanceId(String oldStatus, String status, String processInstanceId) {
        if (!oldStatus.equals(ProcessStatusEnum.BJ.toString()) && !oldStatus.equals(ProcessStatusEnum.ZZ.toString())) {
            //更新扩展流程历史的状态
            LambdaUpdateWrapper<FlowExtendHisprocinst> extendHisprocinstLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
            extendHisprocinstLambdaUpdateWrapper.set(FlowExtendHisprocinst::getProcessStatus, status)
                    .eq(FlowExtendHisprocinst::getProcessInstanceId, processInstanceId);
            this.update(extendHisprocinstLambdaUpdateWrapper);
            //更新扩展流程实例的状态
            LambdaUpdateWrapper<FlowExtendProcinst> extendProcinstLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
            extendProcinstLambdaUpdateWrapper.set(FlowExtendProcinst::getProcessStatus, status)
                    .eq(FlowExtendProcinst::getProcessInstanceId, processInstanceId);
            extendProcinstService.update(extendProcinstLambdaUpdateWrapper);
        }
    }
}
